package com.yf.interceptor;

import com.yf.service.RedisService;
import com.yf.utils.UserContext;
import com.yf.utils.Utils;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Log4j2
@Component
public class LogInterceptor implements HandlerInterceptor {
    @Autowired
    RedisService redisService;
    private static final String blackUserFlag = "wo3$&";

    @Value("${custom.deable-incepter}")
    private Boolean isDev;

    private boolean checkCookie(Cookie[] cookies) {
        if (cookies != null) {
            for (Cookie c: cookies) {
                final String name = c.getName();
                if (LogInterceptor.blackUserFlag.equals(name)) {
                    return true;
                }
            }
        }
        return false;
    }

    void informLogin(HttpServletResponse response) {
        try {
            response.setContentType("application/json;charset=UTF-8");
            final String msg = "{\"code\":101,\"msg\":\"please login\",\"data\":null}";
            final PrintWriter writer = response.getWriter();
            writer.write(msg);
            writer.close();
        } catch (IOException ignored) {
            //
        }
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
//        if (isDev) {
//            return true;
//        }

        final String method = request.getMethod().toUpperCase();
        if ("OPTIONS".equals(method)) {
            return true;
        }

        final String uri = request.getRequestURI();
        if (uri.equals("/api/v1/user/reset/pass")) {
            return true;
        }
        if (uri.startsWith("/api/v1/register")) {
            return true;
        }

        if (uri.equals("/api/v1/login") || uri.startsWith("/api/v1/wechat")) {
            return true;
        }

        if (uri.startsWith("/api/v1/user/reset")) {
            return true;
        }


        String token = request.getHeader("Authorization");
        log.info("token:" + token);
        if (Utils.isNullOrEmpty(token)) {
            informLogin(response);
            return false;
        }

        int uid = 0;
        final int blackTag = token.lastIndexOf('_');
        final int roleIdx = token.lastIndexOf('&');

        // 解码用户 ID
        if (blackTag != -1) {
            uid = Utils.decodeUserId(token.substring(0, blackTag));
        } else if (roleIdx != -1) {
            uid = Utils.decodeUserId(token.substring(0, roleIdx));
        } else {
            uid = Utils.decodeUserId(token);
        }

        // 无效用户
        if (uid == 0) {
            informLogin(response);
            return false;
        }

        log.warn(String.format("[user=%d] %s", uid, uri));

        final String agent = request.getHeader("User-Agent");
        String ua;
        if (Utils.isNullOrEmpty(agent)) {
            ua = Utils.defaultAgent;
        } else {
            ua = Utils.digestPasswd(agent);
        }

        // 检查用的 User agent 是否发送变化
        final boolean b = redisService.checkLogStatus(String.valueOf(uid), ua);
        if (!b) {
            informLogin(response);
            return false;
        }

        if (blackTag !=-1 || checkCookie(request.getCookies())) {
            UserContext.markBlackUser(Boolean.TRUE);
            redisService.cacheUserInfoLong(uid, "black", "1");
        }

        UserContext.setUserId(uid);
        if (roleIdx != -1) {
            String role = token.substring(roleIdx + 1);
            int priority = Utils.decodeUserId(role);
            UserContext.setUserRole(priority);
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserContext.remove();
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
